package cn.yesway.mapshifting.common.utils;

import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Map.Entry;
import java.util.TreeMap;

import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;

/**
 * json格式是否合法正则表达式
 * 
 * @version : Ver 1.0
 * @author : <a href="mailto:358911056@qq.com">hubo</a>
 * @date : 2015-8-4 下午4:12:35
 */
public class ValidateJsonUtils {

	private static CharacterIterator it;
	private static char c;
	private static int col;

	public ValidateJsonUtils() {
	}

	/**
	 * 验证一个字符串是否是合法的JSON串
	 * 
	 * @param input
	 *            要验证的字符串
	 * @return true-合法 ，false-非法
	 */
	public static boolean validate(String input) {
		input = input.trim();
		input = replaceChar(input);
		boolean ret = valid(input);
		return ret;
	}

	private static boolean valid(String input) {
		if ("".equals(input))
			return true;

		boolean ret = true;
		it = new StringCharacterIterator(input);
		c = it.first();
		col = 1;
		if (!value()) {
			ret = error("value", 1);
		} else {
			skipWhiteSpace();
			if (c != CharacterIterator.DONE) {
				ret = error("end", col);
			}
		}

		return ret;
	}

	private static boolean value() {
		return literal("true") || literal("false") || literal("null")
				|| string() || number() || object() || array();
	}

	private static boolean literal(String text) {
		CharacterIterator ci = new StringCharacterIterator(text);
		char t = ci.first();
		if (c != t)
			return false;

		int start = col;
		boolean ret = true;
		for (t = ci.next(); t != CharacterIterator.DONE; t = ci.next()) {
			if (t != nextCharacter()) {
				ret = false;
				break;
			}
		}
		nextCharacter();
		if (!ret)
			error("literal " + text, start);
		return ret;
	}

	private static boolean array() {
		return aggregate('[', ']', false);
	}

	private static boolean object() {
		return aggregate('{', '}', true);
	}

	private static boolean aggregate(char entryCharacter, char exitCharacter,
			boolean prefix) {
		if (c != entryCharacter)
			return false;
		nextCharacter();
		skipWhiteSpace();
		if (c == exitCharacter) {
			nextCharacter();
			return true;
		}

		for (;;) {
			if (prefix) {
				int start = col;
				if (!string())
					return error("string", start);
				skipWhiteSpace();
				if (c != ':')
					return error("colon", col);
				nextCharacter();
				skipWhiteSpace();
			}
			if (value()) {
				skipWhiteSpace();
				if (c == ',') {
					nextCharacter();
				} else if (c == exitCharacter) {
					break;
				} else {
					return error("comma or " + exitCharacter, col);
				}
			} else {
				return error("value", col);
			}
			skipWhiteSpace();
		}

		nextCharacter();
		return true;
	}

	private static boolean number() {
		if (!Character.isDigit(c) && c != '-')
			return false;
		int start = col;
		if (c == '-')
			nextCharacter();
		if (c == '0') {
			nextCharacter();
		} else if (Character.isDigit(c)) {
			while (Character.isDigit(c))
				nextCharacter();
		} else {
			return error("number", start);
		}
		if (c == '.') {
			nextCharacter();
			if (Character.isDigit(c)) {
				while (Character.isDigit(c))
					nextCharacter();
			} else {
				return error("number", start);
			}
		}
		if (c == 'e' || c == 'E') {
			nextCharacter();
			if (c == '+' || c == '-') {
				nextCharacter();
			}
			if (Character.isDigit(c)) {
				while (Character.isDigit(c))
					nextCharacter();
			} else {
				return error("number", start);
			}
		}
		return true;
	}

	private static boolean string() {
		if (c != '"')
			return false;

		int start = col;
		boolean escaped = false;
		for (nextCharacter(); c != CharacterIterator.DONE; nextCharacter()) {
			if (!escaped && c == '\\') {
				escaped = true;
			} else if (escaped) {
				if (!escape()) {
					return false;
				}
				escaped = false;
			} else if (c == '"') {
				nextCharacter();
				return true;
			}
		}
		return error("quoted string", start);
	}

	private static boolean escape() {
		int start = col - 1;
		if (" \\\"/bfnrtu".indexOf(c) < 0) {
			return error(
					"escape sequence  \\\",\\\\,\\/,\\b,\\f,\\n,\\r,\\t  or  \\uxxxx ",
					start);
		}
		if (c == 'u') {
			if (!ishex(nextCharacter()) || !ishex(nextCharacter())
					|| !ishex(nextCharacter()) || !ishex(nextCharacter())) {
				return error("unicode escape sequence  \\uxxxx ", start);
			}
		}
		return true;
	}

	private static boolean ishex(char d) {
		return "0123456789abcdefABCDEF".indexOf(c) >= 0;
	}

	private static char nextCharacter() {
		c = it.next();
		++col;
		return c;
	}

	private static void skipWhiteSpace() {
		while (Character.isWhitespace(c)) {
			nextCharacter();
		}
	}

	private static boolean error(String type, int col) {
		System.out.printf("type: %s, col: %s%s", type, col,
				System.getProperty("line.separator"));
		return false;
	}
	
	public static String replaceChar(String content){
		return content.replace("\r", "").replace("\n", "").replace("\t", "");
	}

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		String jsonStr = "{\"wgs84Positions\": {\"pos1\": {\"lat\":  40,\"lon\":  23.456},\"pos2\": {\"lat\":  140,\"lon\":  123.456}}}";
		
		/*System.out.println(jsonStr + ":"
				+ ValidateJsonUtils.validate(jsonStr));*/
		
		 Gson gson = new Gson();
		 TreeMap<String, Object> maps = gson.fromJson(jsonStr, TreeMap.class);
		 LinkedTreeMap<String, Object> obj =  (LinkedTreeMap<String, Object>) maps.get("wgs84Positions");
		 
		 for(Entry<String, Object> entry : obj.entrySet()){
			 LinkedTreeMap<String, Object> temp =  (LinkedTreeMap<String, Object>) entry.getValue();
			 System.out.println(entry.getKey() + "\t==> " + temp.get("lat") + "\t" + temp.get("lon"));
		 }
		 
		
	}

}
